package be.ipl.diavoloz.modele;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;

import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MapKeyJoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotBlank;

@Entity
@Table(schema="DIAVOLOZ", name="PARTIE")
public class Partie implements Serializable{

	private static final long serialVersionUID = 528709854512096419L;
	
	@Enumerated
	private Etat etat = Etat.ATTENTE_JOUEURS;
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;
	
	@NotNull
	@NotBlank
	private String nom;

	@OneToMany
	private List<Tour> journal;
	
	@OneToMany
	private List<Demons> demonsRoses;
	@OneToMany
	private List<Demons> demonsBleus;
	@OneToMany
	private List<Demons> demonsVerts;
	
	@ElementCollection
	@CollectionTable(schema="DIAVOLOZ", name="JOUEURS_PARTIES")
	@Column(name="POINTS")
	@MapKeyJoinColumn(name="JOUEUR_ID")
	private Map<Joueur, Integer> mesPoints;
	
	@OneToOne
	private Demons demonNoir;
	
	@Column
	private Calendar dateDebut;
	
	@OneToMany
	private List<De> deRose;
	@OneToMany
	private List<De> deBleu;
	@OneToMany
	private List<De> deVert;
	
	@OneToOne
	private De deOrdre;
	
	@OneToMany
	private List<Joueur> listeJoueurs;
	
	protected Partie(){
	}
	
	public Partie(String nom){
		this.nom = nom;
		this.dateDebut = new GregorianCalendar();
		this.journal = new ArrayList<Tour>();

		this.deBleu = new ArrayList<De>();
		this.deRose = new ArrayList<De>();
		this.deVert = new ArrayList<De>();
		this.deOrdre = new DeOrdre();
		
		this.demonsBleus = new ArrayList<Demons>();
		this.demonsRoses = new ArrayList<Demons>();
		this.demonsVerts = new ArrayList<Demons>();
		this.demonNoir = new Demons("Mr Popo", Couleur.NOIR, null);
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((dateDebut == null) ? 0 : dateDebut.hashCode());
		result = prime * result + ((deBleu == null) ? 0 : deBleu.hashCode());
		result = prime * result + ((deOrdre == null) ? 0 : deOrdre.hashCode());
		result = prime * result + ((deRose == null) ? 0 : deRose.hashCode());
		result = prime * result + ((deVert == null) ? 0 : deVert.hashCode());
		result = prime * result
				+ ((demonNoir == null) ? 0 : demonNoir.hashCode());
		result = prime * result
				+ ((demonsBleus == null) ? 0 : demonsBleus.hashCode());
		result = prime * result
				+ ((demonsRoses == null) ? 0 : demonsRoses.hashCode());
		result = prime * result
				+ ((demonsVerts == null) ? 0 : demonsVerts.hashCode());
		result = prime * result + ((etat == null) ? 0 : etat.hashCode());
		result = prime * result + id;
		result = prime * result + ((journal == null) ? 0 : journal.hashCode());
		result = prime * result
				+ ((listeJoueurs == null) ? 0 : listeJoueurs.hashCode());
		result = prime * result
				+ ((mesPoints == null) ? 0 : mesPoints.hashCode());
		result = prime * result + ((nom == null) ? 0 : nom.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Partie other = (Partie) obj;
		if (dateDebut == null) {
			if (other.dateDebut != null)
				return false;
		} else if (!dateDebut.equals(other.dateDebut))
			return false;
		if (deBleu == null) {
			if (other.deBleu != null)
				return false;
		} else if (!deBleu.equals(other.deBleu))
			return false;
		if (deOrdre == null) {
			if (other.deOrdre != null)
				return false;
		} else if (!deOrdre.equals(other.deOrdre))
			return false;
		if (deRose == null) {
			if (other.deRose != null)
				return false;
		} else if (!deRose.equals(other.deRose))
			return false;
		if (deVert == null) {
			if (other.deVert != null)
				return false;
		} else if (!deVert.equals(other.deVert))
			return false;
		if (demonNoir == null) {
			if (other.demonNoir != null)
				return false;
		} else if (!demonNoir.equals(other.demonNoir))
			return false;
		if (demonsBleus == null) {
			if (other.demonsBleus != null)
				return false;
		} else if (!demonsBleus.equals(other.demonsBleus))
			return false;
		if (demonsRoses == null) {
			if (other.demonsRoses != null)
				return false;
		} else if (!demonsRoses.equals(other.demonsRoses))
			return false;
		if (demonsVerts == null) {
			if (other.demonsVerts != null)
				return false;
		} else if (!demonsVerts.equals(other.demonsVerts))
			return false;
		if (etat != other.etat)
			return false;
		if (id != other.id)
			return false;
		if (journal == null) {
			if (other.journal != null)
				return false;
		} else if (!journal.equals(other.journal))
			return false;
		if (listeJoueurs == null) {
			if (other.listeJoueurs != null)
				return false;
		} else if (!listeJoueurs.equals(other.listeJoueurs))
			return false;
		if (mesPoints == null) {
			if (other.mesPoints != null)
				return false;
		} else if (!mesPoints.equals(other.mesPoints))
			return false;
		if (nom == null) {
			if (other.nom != null)
				return false;
		} else if (!nom.equals(other.nom))
			return false;
		return true;
	}

	public String getNom(){
		return this.nom;
	}
	
	public Calendar getDateDebut(){
		return this.dateDebut;
	}

	public Etat getEtat() {
		return etat;
	}

	public List<Tour> getJournal() {
		return journal;
	}

	public List<De> getDeRose() {
		return deRose;
	}

	public List<De> getDeBleu() {
		return deBleu;
	}

	public List<De> getDeVert() {
		return deVert;
	}

	public De getDeOrdre() {
		return deOrdre;
	}

	public List<Demons> getDemonsRoses() {
		return demonsRoses;
	}

	public List<Demons> getDemonsBleus() {
		return demonsBleus;
	}

	public List<Demons> getDemonsVerts() {
		return demonsVerts;
	}

	public Demons getDemonNoir() {
		return demonNoir;
	}

	public Integer getId() {
		return this.id;
	}
	
	public List<Joueur> getListeJoueurs() {
		return listeJoueurs;
	}

	public boolean ajouterJoueur(Joueur joueur) {
		return this.listeJoueurs.add(joueur);
	}

	public boolean commencerPartie() {
		// TODO Auto-generated method stub
		return false;
	} 
}
